﻿using Doc.SDK.Core.Model;
using Doc.SDK.Core.RequestBuilder;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;


namespace Doc.SDK.Core.Client
{
    public class QQDocClient
    {
        private const string defaultHost = "docs.qq.com";
        private readonly string _clientId;
        private readonly string _clientSecret;
        private readonly string _callbackurl;
        private QQDocUrlBuilder _urlBuilder;
        private QQDocHeaders _headers;

        /// <summary>
        /// 用户授权构造函数
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="clientSecret"></param>
        /// <param name="callbackurl"></param>
        /// <param name="host"></param>
        public QQDocClient(string clientId, string clientSecret,string callbackurl, string host = defaultHost)
        {
            _clientId = clientId;
            _clientSecret = clientSecret;
            _callbackurl = callbackurl;
            _urlBuilder = new QQDocUrlBuilder(host);
        }

        public QQDocClient(QQDocHeaders headers,string host=defaultHost)
        {
            _headers = headers;
            _urlBuilder = new QQDocUrlBuilder(defaultHost);
        }

        #region 用户授权       
        /// <summary>
        /// 发起授权
        /// </summary>
        /// <returns></returns>
        public string GetAuthorize()
        {
            var request = new GetRequest()
                .AddParam("client_id", _clientId)
                .AddParam("redirect_uri", _callbackurl)
                .AddParam("response_type", "code")
                .AddParam("scope", "all");
                //.AddParam("state", Guid.NewGuid().ToString("N"));
            return _urlBuilder.Build("/oauth/v2/authorize", request);
        }
        /// <summary>
        /// 获取 Token
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<QQDocTokenReq> GetToken(string code)
        {
            var request = new GetRequest()
               .AddParam("client_id", _clientId)
               .AddParam("client_secret", _clientSecret)
               .AddParam("redirect_uri", _callbackurl)               
               .AddParam("grant_type", "authorization_code")
               .AddParam("code", code);
            var url = _urlBuilder.Build("/oauth/v2/token", request);
            return await HttpRequest.GetAsync<QQDocTokenReq>(url).ConfigureAwait(false);
        }
        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public async Task<QQDocRequest<UserinfoReq>> GetUserinfo(string access_token)
        {
            var request = new GetRequest()
               .AddParam("access_token", access_token);
            var url = _urlBuilder.Build("/oauth/v2/userinfo", request);
            return await HttpRequest.GetAsync<QQDocRequest<UserinfoReq>>(url);
        }
        /// <summary>
        /// 刷新 Access Token
        /// </summary>
        /// <param name="refresh_token"></param>
        /// <returns></returns>
        public async Task<QQDocTokenReq> GetRefreshtoken(string refresh_token)
        {
            var request = new GetRequest()
               .AddParam("client_id", _clientId)
               .AddParam("client_secret", _clientSecret)
               .AddParam("grant_type", "refresh_token")
               .AddParam("refresh_token", refresh_token);
            var url = _urlBuilder.Build("/oauth/v2/token", request);
            return await HttpRequest.GetAsync<QQDocTokenReq>(url);
        }
        #endregion

        #region 文件操作

        
        /// <summary>
        /// 创建文档
        /// </summary>
        /// <param name="rsp"></param>
        /// <returns></returns>
        public async Task<QQDocRequest<Reqfileinfo>> FilesCreate(Rspfiles rsp)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files");
            return await HttpRequest.PostAsync<QQDocRequest<Reqfileinfo>>(url,  _headers, rsp.ToJson());
        }
        /// <summary>
        /// 查询文档
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesSelect(string fileID)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files/"+fileID+"/metadata");
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }
        /// <summary>
        /// 更新文档名称
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesUpdate(string fileID, Rspfilesupdate rsp)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files/"+fileID);
            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers,rsp.ToJson());
        }

        /// <summary>
        /// 移动文档
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesUpdate(string fileID, Rspfilesmove rsp)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files/"+fileID+"/move");
            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 删除文档
        /// </summary>
        /// <param name="fileID"></param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesDelete(string fileID)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files/"+fileID);
            return await HttpRequest.DeleteAsync<QQDocRequest<object>>(url, _headers);
        }
        /// <summary>
        /// 生成副本
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesCopy(string fileID, Rspfilescopy rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/copy");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 星标文档
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesStar(string fileID, Rspfilesstar rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/star");
            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 置顶文档
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesPin(string fileID, Rspfilespin rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/pin");
            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 设置水印
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesWatermark(string fileID, Rspfileswatermark rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/watermark");
            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 获取克隆票据
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesCopyKey(string fileID, Rspfilesclonekey rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/clone-key");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 克隆文件
        /// </summary>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesClone(Rspfilesclone rsp)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files/clone");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }

        /// <summary>
        /// 导出文档
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesAsyncExport(string fileID, Rspfilesasyncexport rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/async-export");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 导出进度查询
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesExportProgress(string fileID, string operationID)
        {
            var request = new GetRequest()
                .AddParam("operationID", operationID);
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/export-progress",request);
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }
        /// <summary>
        /// 预导入文档
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesPreImport(Rspfilespreimport rep)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files/pre-import");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers,rep.ToJson());
        }
        /// <summary>
        /// 异步导入文档
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesAsyncImport(Rspfilesasyncimport rep)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/files/async-import");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers, rep.ToJson());
        }

        /// <summary>
        /// 查询导入进度
        /// </summary>
        /// <param name="progressQueryID">进度查询凭证</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesImportProgress(string progressQueryID)
        {
            var request = new GetRequest()
                .AddParam("progressQueryID", progressQueryID);
            string url = _urlBuilder.Build("/openapi/drive/v2/files/import-progress", request);
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }

        /// <summary>
        /// 创建快捷方式
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FilesShortcut(string fileID, Rspfilesshortcut rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/shortcut");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers, rsp.ToJson());
        }
        #endregion
        #region 文件夹操作
        /// <summary>
        /// 添加文件夹
        /// </summary>
        /// <param name="rsp">请求体</param>
        /// <returns></returns>
        public async Task<QQDocRequest<ReqFoldersInfo>> FoldersAdd(Rspfolders rsp)
        {
            string url = _urlBuilder.Build("/openapi/drive/v2/folders");
            return await HttpRequest.PostAsync<QQDocRequest<ReqFoldersInfo>>(url, _headers, rsp.ToJson());
        }
        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="folderID">	文件夹唯一标识</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FoldersDelete(string folderID, RspfoldersDelete rsp)
        {
            var request = new GetRequest()
                .AddParam("listType", rsp.listType)
                .AddParam("shareKey", rsp.shareKey)
                .AddParam("originFolderID", rsp.originFolderID);
            string url = _urlBuilder.Build($"/openapi/drive/v2/folders/{folderID}", request);
            return await HttpRequest.DeleteAsync<QQDocRequest<object>>(url, _headers);
        }
        /// <summary>
        /// 查询文件夹信息
        /// </summary>
        /// <param name="folderID">	文件夹唯一标识</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FoldersMetadata(string folderID)
        {            
            string url = _urlBuilder.Build($"/openapi/drive/v2/folders/{folderID}/metadata");
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }

        /// <summary>
        /// 查询文件夹权限
        /// </summary>
        /// <param name="folderID">	文件夹唯一标识</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FoldersPermission(string folderID)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/folders/{folderID}/permission");
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }
        
        /// <summary>
        /// 获取文档列表
        /// </summary>
        /// <param name="folderID">	文件夹唯一标识</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> FoldersList(string folderID, Rspfolderslist rsp)
        {
            var request = new GetRequest()
                .AddParam("sortType", rsp.sortType)
                .AddParam("asc", rsp.asc.ToString())
                .AddParam("start", rsp.start.ToString())
                .AddParam("limit", rsp.limit.ToString());
            string url = _urlBuilder.Build($"/openapi/drive/v2/folders/{folderID}",request);
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }
        #endregion

        #region 权限操作
        /// <summary>
        /// 查看文档权限
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthPermission(string fileID)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/permission");
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }
        /// <summary>
        /// 设置文档权限
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthPermissionSet(string fileID,RspAuthpermission rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/permission");
            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers,rsp.ToJson());
        }

        /// <summary>
        /// 查询用户访问权限
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthAccess(string fileID)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/access");
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }

        /// <summary>
        /// 申请文档权限
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthPermissionApply(string fileID,RspAuthapply rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/permission/apply");
            return await HttpRequest.PostAsync<QQDocRequest<object>>(url, _headers,rsp.ToJson());
        }

        /// <summary>
        /// 添加协作成员
        /// </summary>
        /// <param name="fileID">文档唯一标识，详见文档ID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthCollaborators(string fileID, List<RspAuthcollaborators> rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/collaborators");
            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers, JsonConvert.SerializeObject(rsp));
        }

        /// <summary>
        /// 移除协作成员
        /// </summary>
        /// <param name="folderID">	文件夹唯一标识</param>
        /// <param name="openID">被删除权限者，填目标用户的openID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthDelete(string fileID, string openID)
        {
            var request = new GetRequest()
                .AddParam("type", "user")
                .AddParam("id", openID);
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/collaborators", request);
            return await HttpRequest.DeleteAsync<QQDocRequest<object>>(url, _headers);
        }
        /// <summary>
        /// 查询协作成员
        /// </summary>
        /// <param name="folderID">	文件夹唯一标识</param>
        /// <param name="openID">被删除权限者，填目标用户的openID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthDelete(string fileID)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/collaborators");
            return await HttpRequest.GetAsync<QQDocRequest<object>>(url, _headers);
        }

        /// <summary>
        /// 转让文档所有权
        /// </summary>
        /// <param name="folderID">	文件夹唯一标识</param>
        /// <param name="openID">被删除权限者，填目标用户的openID</param>
        /// <returns></returns>
        public async Task<QQDocRequest<object>> AuthOwnership(string fileID,RspAuthownership rsp)
        {
            string url = _urlBuilder.Build($"/openapi/drive/v2/files/{fileID}/ownership");

            return await HttpRequest.PatchAsync<QQDocRequest<object>>(url, _headers,rsp.ToJson());
        }
        #endregion
        
    }
}
